/*
 * ColorsHSV.h
 *
 *  Created on: Feb 19, 2009
 *      Author: vuk
 */

#ifndef COLORSHSV_H_
#define COLORSHSV_H_

#include <iostream>
using namespace std;

//Jednostavna klasa za HSV boje

class ColorHSV
{

protected:
	uchar *hsv;

public:

	//bez destruktora zbog efikasnosti
	//nemora se raditi koporanje

	ColorHSV()
	{
		hsv = new uchar[3];
		hsv[0]=0;
		hsv[1]=0;
		hsv[2]=0;
	}

	ColorHSV(uchar *u){hsv=u;}

	ColorHSV(uchar H, uchar S, uchar V)
	{
		hsv = new uchar[3];
		hsv[0]=H;
		hsv[1]=S;
		hsv[2]=V;
	}

	void set(uchar H, uchar S, uchar V)
	{
		hsv[0]=H;
		hsv[1]=S;
		hsv[2]=V;
	}

	uchar H()	{	return hsv[0];}
	uchar S()	{	return hsv[1];}
	uchar V()	{	return hsv[2];}

	void setH(uchar c)	{	hsv[0]=c;}
	void setS(uchar c)	{	hsv[1]=c;}
	void setV(uchar c)	{	hsv[2]=c;}

	ColorHSV operator=(uchar *a){hsv=a;}

	bool operator>(ColorHSV &c) { return (hsv[0]>c.hsv[0] && hsv[1]>c.hsv[1] && hsv[2]>c.hsv[2]);}
	bool operator<(ColorHSV &c) { return (hsv[0]<c.hsv[0] && hsv[1]<c.hsv[1] && hsv[2]<c.hsv[2]);}
	bool operator<=(ColorHSV &c) { return (hsv[0]<=c.hsv[0] && hsv[1]<=c.hsv[1] && hsv[2]<=c.hsv[2]);}
	bool operator>=(ColorHSV &c) { return (hsv[0]>=c.hsv[0] && hsv[1]>=c.hsv[1] && hsv[2]>=c.hsv[2]);}
	bool operator==(ColorHSV &c) { return (hsv[0]==c.hsv[0] && hsv[1]==c.hsv[1] && hsv[2]==c.hsv[2]);}
	bool operator!=(ColorHSV &c) { return (hsv[0]!=c.hsv[0] && hsv[1]!=c.hsv[1] && hsv[2]!=c.hsv[2]);}

	bool horeH(ColorHSV &c) { return hsv[0]>=c.hsv[0]; } //koristi se kao vece  jednako ali, samo proverava H
	bool loreH(ColorHSV &c) { return hsv[0]<=c.hsv[0]; } //koristi se kao manje jednako, ali samo proverava H

	bool horeSV(ColorHSV &c) { return hsv[1]>=c.hsv[1] && hsv[2]>=c.hsv[2]; } //koristi se kao vece  jednako, ali samo proverava S i V
	bool loreSV(ColorHSV &c) { return hsv[1]<=c.hsv[1] && hsv[2]<=c.hsv[2]; } //koristi se kao manje jednako, ali samo proverava S i V

	bool horeH(int x) { return hsv[0]>=x; } //koristi se kao vece  jednako ali, samo proverava H
	bool loreH(int x) { return hsv[0]<=x; } //koristi se kao manje jednako, ali samo proverava H

	friend ostream &operator<<(ostream &out, const ColorHSV& c)
	{
		return out<<" "<<(int)c.hsv[0]<<" "<<(int)c.hsv[1]<<" "<<(int)c.hsv[2]<<endl;
	}

};


//Klasa koja organizuje HSV boje u skup svih boja koje mogu da se jave
//Ona konstruise pomocu fajla a takodje moze i da snimi u bilo koji fajl promene parametara

class ColorsHSV
{
public:

	ColorHSV rl,rh,gl,gh,bl,bh,dl,dh; //d=dark, braon l=donja h=gornja

	class BadFile{};

	ColorsHSV (const char *fajl)
	{
		fstream f(fajl);
		int h,s,v;
		string str;

		f>>str;
		if (str!="Crvena_donja:")	throw BadFile();
		f>>h>>s>>v;
		rl.set(h, s, v);

		f>>str;
		if(str!="Crvena_gornja:")	throw BadFile();
		f>>h>>s>>v;
		rh.set(h, s, v);

		f>>str;
		if(str!="Zelena_donja:")	throw BadFile();
		f>>h>>s>>v;
		gl.set(h, s, v);

		f>>str;
		if(str!="Zelena_gornja:")	throw BadFile();
		f>>h>>s>>v;
		gh.set(h, s, v);

		f>>str;
		if(str!="Plava_donja:")	throw BadFile();
		f>>h>>s>>v;
		bl.set(h, s, v);

		f>>str;
		if(str!="Plava_gornja:")	throw BadFile();
		f>>h>>s>>v;
		bh.set(h, s, v);

		f>>str;
		if(str!="Braon_donja:")	throw BadFile();
		f>>h>>s>>v;
		dl.set(h, s, v);

		f>>str;
		if(str!="Braon_gornja:")	throw BadFile();
		f>>h>>s>>v;
		dh.set(h, s, v);
	}

	friend istream &operator>>(istream &f, ColorsHSV &c)
	{
		int h,s,v;
		string str;

		f>>str;
		if(str!="Crvena_donja:")	throw BadFile();
		f>>h>>s>>v;
		c.rl.set(h, s, v);

		f>>str;
		if(str!="Crvena_gornja:")	throw BadFile();
		f>>h>>s>>v;
		c.rh.set(h, s, v);

		f>>str;
		if(str!="Zelena_donja:")	throw BadFile();
		f>>h>>s>>v;
		c.gl.set(h, s, v);

		f>>str;
		if(str!="Zelena_gornja:")	throw BadFile();
		f>>h>>s>>v;
		c.gh.set(h, s, v);

		f>>str;
		if(str!="Plava_donja:")	throw BadFile();
		f>>h>>s>>v;
		c.bl.set(h, s, v);

		f>>str;
		if(str!="Plava_gornja:")	throw BadFile();
		f>>h>>s>>v;
		c.bh.set(h, s, v);

		f>>str;
		if(str!="Braon_donja:")	throw BadFile();
		f>>h>>s>>v;
		c.dl.set(h, s, v);

		f>>str;
		if(str!="Braon_gornja:")	throw BadFile();
		f>>h>>s>>v;
		c.dh.set(h, s, v);
	}
	//proveri da li je data boja u opsegu crvene
	bool r(ColorHSV c)
	{
		if(rl.loreH(rh))
			return rl<=c && rh>=c;
		else
			return ( (c.horeH(rl) && c.loreH(180) ) || (c.horeH(0) && c.loreH(rh) ) ) && c.horeSV(rl) && c.loreSV(rh);
	}
	//proveri da li je data boja u opsegu zelene
	bool g(ColorHSV c)
	{
		if(gl.loreH(gh))
			return gl<=c && gh>=c;
		else
			return ( (c.horeH(rl) && c.loreH(180) ) || (c.horeH(0) && c.loreH(rh) ) ) && c.horeSV(rl) && c.loreSV(rh);
	}
	//proveri da li je data boja u opsegu plave
	bool b(ColorHSV c)
	{
		if(bl.loreH(bh))
			return bl<=c && bh>=c;
		else
			return ( (c.horeH(bl) && c.loreH(180) ) || (c.horeH(0) && c.loreH(bh) ) ) && c.horeSV(bl) && c.loreSV(bh);
	}
	//proveri da li je data boja u opsegu braon
	bool d(ColorHSV c)
	{
		if(dl.loreH(dh))
			return dl<=c && dh>=c;
		else
			return ( (c.horeH(dl) && c.loreH(180) ) || (c.horeH(0) && c.loreH(dh) ) ) && c.horeSV(dl) && c.loreSV(dh);
	}

	friend ostream &operator<<(ostream &out, const ColorsHSV& c)
	{
		return 	out<<"Crvena_donja:"<< c.rl<< "Crvena_gornja:"<< c.rh
				   <<"Zelena_donja:"<< c.gl<< "Zelena_gornja:"<< c.gh
				   <<"Plava_donja:"<< c.bl<< "Plava_gornja:"<< c.bh
		           <<"Braon_donja:"<< c.dl<< "Braon_gornja:"<< c.dh;
	}
};

#endif /* COLORSHSV_H_ */
